using System;
namespace MathSharp
{
	public abstract class ScriptException: Exception {
		
		public ScriptException(string fileName, int line, int column, int code, string message, params object[] args):
			base(MakeErrorMesage(fileName, line, column, code, message, args)) {
			this.FileName = fileName;
			this.Line = line;
			this.Column = column;
			this.Code = code;
			this.Message = message.format(args);
		}
		
		string MakeErrorMesage(string fileName, int line, int column, int code, string message, params object[] args) {
			string res = "Ошибка Math#";
			if (code != 0)
				res += " {0}{1}".format(GetCodePrefix(), code);
			
			if (fileName == null || fileName.IsNullOrWhiteSpace())
				res += " в файле (нет)";
			else
				res += " в файле {0}".format(fileName);
			
			if (line > 0) {
				if (column > 0)
					res += " в {0}:{1}".format(line, column);
				else
					res += " в строке {0}".format(line);
			}
			
			res += ": {0}".format(message.format(args));
			return res;
		}

		public string FileName {
			get;
			protected set;
		}
		
		public int Line {
			get;
			protected set;
		}
		
		public int Column {
			get;
			protected set;
		}
		
		public int Code {
			get;
			protected set;
		}
		
		protected string IntMessaege {
			get;
			set;
		}
		
		protected abstract string GetCodePrefix();
	}
	
	public class ParseException: ScriptException
	{
		public ParseException(string fileName, int line, int column, int code, string message, params object[] args):
			base(fileName, line, column, code, message, args) {
		}
		
		protected override string GetCodePrefix ()
		{
			return "P";
		}
		
		public ParseException Rethrow(string filename, int line, int column, int code) {
			return new ParseException((this.FileName == null || this.FileName.IsNullOrWhiteSpace())?filename:this.FileName,
			                          this.Line + line,
			                          this.Column + column,
			                          (this.Code == 0)?Code:this.Code,
			                          this.IntMessage);
		}
	}
	
	public class PrepareExecuteException: ScriptException
	{
		public PrepareExecuteException(string fileName, int line, int column, int code, string message, params object[] args):
			base(fileName, line, column, code, message, args) {
		}
		
		protected override string GetCodePrefix ()
		{
			return "PE";
		}
		
		public ParseException Rethrow(string filename, int line, int column, int code) {
			return new ParseException((this.FileName == null || this.FileName.IsNullOrWhiteSpace())?filename:this.FileName,
			                          this.Line + line,
			                          this.Column + column,
			                          (this.Code == 0)?Code:this.Code,
			                          this.IntMessage);
		}
	}
	
	public class ExecuteException: ScriptException
	{
		public ExecuteException(string fileName, int line, int column, int code, string message, params object[] args):
			base(fileName, line, column, code, message, args) {
		}
		
		protected override string GetCodePrefix ()
		{
			return "E";
		}
		
		public ParseException Rethrow(string filename, int line, int column, int code) {
			return new ParseException((this.FileName == null || this.FileName.IsNullOrWhiteSpace())?filename:this.FileName,
			                          this.Line + line,
			                          this.Column + column,
			                          (this.Code == 0)?Code:this.Code,
			                          this.IntMessage);
		}
	}
}

